
#ifndef _MEMBER_BMenu_H_
#define _MEMBER_BMenu_H_

#include <BRect>
#include <BStyle>
#include <BIcon>
#include <BMenu>
#include <BAction>
#include <BLayout>
#include <BImage>
#include "IAlignment.h"

#define menu_member(menu)		((member_BMenu*)((BMenu*)menu)->_ptr)

namespace BWE
{
	class MenuItem : public IAlignment
	{
	public:
		inline MenuItem()
		{
			dirty = true;
		}
		inline MenuItem(BAction* action)
		{
			dirty = true;
			this->action = action;
		}
		inline MenuItem(BMenu* menu)
		{
			dirty = true;
			this->menu = menu;
		}

		inline void freshSize(const BStyle* style, const BFont* font)
		{
			if (namedIcon.empty())
			{
				if (action)
				{
					if (action->name().size())
						namedIcon = style->icon(action->name());
					if (namedIcon.empty())
						namedIcon = style->icon(action->text());
				}
				if (menu)
				{
					if (menu->name().size())
						namedIcon = style->icon(menu->name());
					if (namedIcon.empty())
						namedIcon = style->icon(menu->title());
				}
			}
			t_text.reset();
			const BString& text = this->text();
			if (text.size())
			{
				bool transed = style && style->translate(text, t_text);
				if (!transed && menu)
				{
					if (const BStyle* menuStyle = menu->realStyle())
						menuStyle->translate(text, t_text);
				}
				if (t_text.size())
					ia_textSize = font->textSize(t_text);
				else
					ia_textSize = font->textSize(text);
			}
			bool hasIcon = this->graph() || this->icon();
			bool showIcon = hasIcon || (ia_form >= Form_IconOnly && ia_form <= Form_IconUnderText);
			if (ia_form == Form_IconAlone && !hasIcon)
				showIcon = false;
			if (ia_form == Form_TextAlone && text.empty() && hasIcon)
				showIcon = true;
			if (showIcon)
			{
				if (font)
				{
					if (ia_imageSize.width() < 1)
						ia_imageSize.width() = font->size();
					if (ia_imageSize.height() < 1)
						ia_imageSize.height() = font->size();
				}
			}
			adjust(BRect());
			hsize = ia_hintSize;
		}
		inline void adjustRect(int x, int y, int w, int h)
		{
			rect.set(x, y, w, h);
			adjust(rect);
		}

		inline bool empty() const
		{
			return action.empty() && menu.empty();
		}
		inline bool enabled() const
		{
			if (action)
				return action->enabled();
			if (menu)
				return menu->enabled();
			return false;
		}
		inline const BString& text() const
		{
			if (action)
				return action->text();
			if (menu)
				return menu->title();
			return t_text;
		}
		inline const BIcon* icon() const
		{
			const BIcon* realIcon = 0;
			if (action)
				realIcon = action->icon();
			if (menu)
				realIcon = menu->titleIcon();
			if (!realIcon)
				realIcon = namedIcon;
			return realIcon;
		}
		inline Graph graph() const
		{
			if (action)
			{
				return action->graph();
			}
			return Graph_None;
		}

		inline bool operator == (const BAction* action)
		{
			return this->action == action;
		}
		inline bool operator == (const BMenu* menu)
		{
			return this->menu == menu;
		}

		bool				dirty;
		BHolder<BAction>	action;
		BHolder<BMenu>		menu;
		BHolder<BIcon>		namedIcon;

		BString				t_text;
		BSize				hsize;
		BRect				rect;
		BRect				arrowRect;
	};

	class member_BMenu : public BObject
	{
		friend class BMenu;
	public:
		member_BMenu(BMenu* menu);
		~member_BMenu();

		void raiseSignal(int signal, const BValue& value = BValue());

		BMenu* locateMenu(const BString& path, BString& temp);

		void freshRects();
		
		void slotActionTriggered(BObject* object, const BValue& value);
		void slotActionRenamed(BObject* object, const BValue& value);
		void slotActionTextChanged(BObject* object, const BValue& value);
		void slotActionIconChanged(BObject* object, const BValue& value);
		void slotActionChecked(BObject* object, const BValue& value);

		void slotMenuRenamed(BObject* object, const BValue& value);
		void slotMenuIconChanged(BObject* object, const BValue& value);
		void slotMenuTitleChanged(BObject* object, const BValue& value);
		void slotMenuStyleChanged(BObject* object, const BValue& value);

		BMenu*				boss;
		Form				form;
		Align				align;
		int					spacing;
		BSize				iconSize;
		BIconHolder			arrowIcon;
		BSize				arrowSize;
		Graph				arrowGraph;
		BSize				separatorSize;
		BImageHolder		separatorImage;

		bool				dirty;
		bool				expanded;
		int					hoverIndex;
		bool				pressed;
		BArray<MenuItem>	items;
		BSize				conentSize;
	};
}

#endif